package org.ns.framework.datasource.redis;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.params.SetParams;

public class RedisSource {

	private final JedisPool jedisPool;
	private RedisConfig config;
	public RedisSource(RedisConfig config) {
		String password = config.getPassword();
		int database = config.getDatabase();
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxIdle(config.getMaxIdle());
		jedisPoolConfig.setMinIdle(config.getMinIdle());
		jedisPoolConfig.setTestOnReturn(true);
		jedisPoolConfig.setTestOnBorrow(true);
		jedisPool = new JedisPool(jedisPoolConfig, config.getHost(), config.getPort(), 10000, password, database);
		this.config = config;
	}

	public Jedis getJedis() {
		return jedisPool.getResource();
	}

	public long rpush(String key, String... values) {
		try (Jedis jedis = getJedis();) {
			return jedis.rpush(key, values);
		}
	}
	public long lpush(String key, String... values) {
		try (Jedis jedis = getJedis();) {
			return jedis.lpush(key, values);
		}
	}


	public List<String> blpop(int timeout, String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.blpop(timeout, key);
		}
	}

	public long llen(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.llen(key);
		}
	}

	public boolean ping() {
		try (Jedis jedis = getJedis();) {
			return jedis.ping() != null;
		}
	}

	public String set(String key, String value) {
		try (Jedis jedis = getJedis();) {
			return jedis.set(key, value);
		}
	}

	public String set(String key, String value, SetParams setParams) {
		try (Jedis jedis = getJedis();) {
			return jedis.set(key, value, setParams);
		}
	}

	public String get(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.get(key);
		}
	}

	public long hset(String key, String field, String value) {
		try (Jedis jedis = getJedis();) {
			return jedis.hset(key, field, value);
		}
	}
	public long sadd(String key, String... members) {
		try (Jedis jedis = getJedis();) {
			return jedis.sadd(key, members);
		}
	}
	
	public long srem(String key, String... members) {
		try (Jedis jedis = getJedis();) {
			return jedis.srem(key, members);
		}
	}
	
	public Set<String> smembers(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.smembers(key);
		}
	}
	public List<String> smembersToList(String key) {
		Set<String> strings = smembers(key);
		if (strings == null) {
			return new ArrayList<>();
		} else {
			return new ArrayList<>(strings);
		}
	}
	
	public long scard(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.scard(key);
		}
	}
	
	public long hlen(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.hlen(key);
		}
	}

	public String hget(String key, String field) {
		try (Jedis jedis = getJedis();) {
			return jedis.hget(key, field);
		}
	}
	public Map<String, String> hgetAll(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.hgetAll(key);
		}
	}


	public Set<String> hkeys(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.hkeys(key);
		}
	}
	
	public long hdel(String key, String... fields) {
		try (Jedis jedis = getJedis();) {
			return jedis.hdel(key, fields);
		}
	}
	public long publish(String channel, String message) {
		try (Jedis jedis = getJedis();) {
			return jedis.publish(channel, message);
		}
	}

	public long del(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.del(key);
		}
	}
	public long expire(String key, int seconds) {
		try (Jedis jedis = getJedis();) {
			return jedis.expire(key, seconds);
		}
	}
	
	public List<Object> transaction(Consumer<Transaction> consumer) {
		try (Jedis jedis = getJedis();) {
			Transaction transaction = jedis.multi();
			consumer.accept(transaction);
			return transaction.exec();
		}
	}
	public static void main(String[] args) {
		RedisConfig redisConfig = new RedisConfig();
		redisConfig.setHost("52.77.239.60");
		RedisSource redisSource = new RedisSource(redisConfig);
		
		System.out.println(redisSource.ping());
		
	}
	
	public RedisConfig getConfig() {
		return config;
	}
	public Jedis newJedis() {
		return new Jedis(config.getHost(), config.getPort()); 
	}
}
